package com.higgins.eventtracking.server;

import java.text.DateFormatSymbols;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class DateUtility {
	public static int getHour(Date date)	{
//		wk = wk - 1;
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		return cal.get(Calendar.HOUR_OF_DAY);
	}
	public static Date createDateByWeek(int wk, int day, int year)	{
//		wk = wk - 1;
		Calendar cal = Calendar.getInstance();
		cal.clear();
		cal.setFirstDayOfWeek(Calendar.MONDAY);
		cal.setMinimalDaysInFirstWeek(5);
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.WEEK_OF_YEAR, wk);
		cal.set(Calendar.DAY_OF_WEEK, day);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}
	public static Date createDateByMonth(int mth, int day, int year)	{
		Calendar cal = Calendar.getInstance();
		cal.clear();
		cal.setFirstDayOfWeek(Calendar.MONDAY);
		cal.setMinimalDaysInFirstWeek(5);
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.MONTH, mth);
		cal.set(Calendar.DAY_OF_MONTH, day);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}
	public static Integer getWeekNumberOfMonth(Date now)	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(getStartOfWeek(now));
		cal.add(Calendar.DAY_OF_MONTH, + 2);		
		int days=cal.get(Calendar.DATE) - 1;
		Integer numberOfWeeks = days/7;
		return numberOfWeeks + 1;
//		return cal.get(Calendar.WEEK_OF_MONTH);
	}	
	public static Integer getWeekNumberOfYear(Date now)	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(getStartOfWeek(now));
		cal.add(Calendar.DAY_OF_MONTH, + 2);		
//		int days=cal.get(Calendar.DATE) - 1;
//		Integer numberOfWeeks = days/7;
//		return numberOfWeeks + 1;
		return cal.get(Calendar.WEEK_OF_YEAR);
	}	
	public static Integer getMonth(Date now)	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(getMidWeek(now));
		return cal.get(Calendar.MONTH);
	}
//	@Deprecated
//	public static Date getStartOfWeek(Date date)	{
//		return getStartOfWeek(getWeekNumberOfYear(date));
//	}
	@Deprecated
	public static Date getStartOfMonth(int monthNumber)	{
		Calendar cal = Calendar.getInstance();
		int year = cal.get(Calendar.YEAR);
		return getStartOfMonth(monthNumber, year);
	}
	public static String getMonth(int month) {
	    return new DateFormatSymbols().getMonths()[month];
	}	
	
	public static Date getStartOfMonth(int monthNumber, int year)	{
		Calendar cal = Calendar.getInstance();
		cal.clear();
		cal.setFirstDayOfWeek(Calendar.MONDAY);
		cal.setMinimalDaysInFirstWeek(5);
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.MONTH, monthNumber);
		cal.set(Calendar.DATE, 1);		
		cal.getTime();
		
		int day = cal.get(Calendar.DAY_OF_WEEK);
		
		if ((day!=Calendar.MONDAY)&&(day!=Calendar.TUESDAY)&&(day!=Calendar.WEDNESDAY))	{
			cal.add(Calendar.WEEK_OF_MONTH, 1);
		}

		cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
	
		return cal.getTime();
	}
	public static Date getEndOfMonth(int monthNumber, int year)	{
		Date returnDate;
		if (monthNumber<11)
			returnDate = getStartOfMonth(monthNumber+1, year);
		else
			returnDate = getStartOfMonth(0, year+1);
		return subtractASecond(returnDate);
	}	
	@Deprecated
	public static Date getEndOfMonth(int monthNumber)	{
		Calendar cal = Calendar.getInstance();
		int year = cal.get(Calendar.YEAR);
		return getEndOfMonth(monthNumber, year);
	}	
	@Deprecated
	public static Date getStartOfWeek(int weekNumber)	{
		Calendar cal = Calendar.getInstance();
		int year = cal.get(Calendar.YEAR);
		return getStartOfWeek(weekNumber, year);
	}
	public static Date getStartOfWeek(int weekNumber, int year)	{
		Calendar cal = Calendar.getInstance();
		cal.clear();
		cal.setFirstDayOfWeek(Calendar.MONDAY);
		cal.setMinimalDaysInFirstWeek(5);
		cal.set(Calendar.YEAR, year);
		cal.set(Calendar.WEEK_OF_YEAR, weekNumber);
		cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		
		return cal.getTime();
	}
	public static Date getEndOfWeek(int weekNumber, int year)	{
		Date returnDate;
		if (weekNumber<52)
			returnDate = getStartOfWeek(weekNumber+1, year);
		else
			returnDate = getStartOfWeek(1, year+1);
		return subtractASecond(returnDate);
	}
	public static Date subtractASecond(Date date)	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.SECOND, -1);
		return cal.getTime();
	}
//	@Deprecated
//	public static Date getEndOfWeek(int weekNumber)	{
//		return getStartOfWeek(weekNumber+1);
//	}
	public static Date getStartOfMonth(Date now)	{
		Integer year = getYear(now);
		Integer month = getMonth(now);
		
		return getStartOfMonth(month, year);
	}
	public static Date getEndOfMonth(Date now)	{
		Integer year = getYear(now);
		Integer month = getMonth(now);
		
		return getEndOfMonth(month, year);
	}
	@Deprecated
	public static Date getStartOfThisMonth()	{
		return getStartOfMonth(getThisMonthNumber(new Date()));
	}
	@Deprecated
	public static Date getStartOfLastMonth()	{
		return getStartOfMonth(getLastMonthNumber(new Date()));
	}
	@Deprecated
	public static Date getStartOfThisMonth(Date now)	{
		return getStartOfMonth(getThisMonthNumber(now));
	}
	@Deprecated
	public static Date getStartOfLastMonth(Date now)	{
		return getStartOfMonth(getLastMonthNumber(now));
	}
	@Deprecated
	public static Integer getLastMonthNumber(Date now)	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(now);
		cal.add(Calendar.DAY_OF_MONTH, +2);
		cal.add(Calendar.MONTH, -1);
		return cal.get(Calendar.MONTH);
	}
	
	public static Boolean isFirstWeekOfMonth(Date date)	{
		return getWeekNumberOfMonth(date).equals(1);
	}
	public static Date getStartOfDay(Date now)	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(now);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}	
	public static Date getEndOfDay(Date now)	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(now);
		cal.set(Calendar.HOUR_OF_DAY, 23);
		cal.set(Calendar.MINUTE, 59);
		cal.set(Calendar.SECOND, 59);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}		
	public static Date getStartOfWeeksAgo(Date now, Integer weeks)	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(now);
		int numberOfDays = cal.get(Calendar.DAY_OF_WEEK) > 1?(cal.get(Calendar.DAY_OF_WEEK)-2):6;
		cal.add(Calendar.DATE, -numberOfDays);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		cal.getTime();
		cal.add(Calendar.WEEK_OF_YEAR, -weeks);
		return cal.getTime();
	}
	public static Date getStartOfWeek(Date now)	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(now);
		int numberOfDays = cal.get(Calendar.DAY_OF_WEEK) > 1?(cal.get(Calendar.DAY_OF_WEEK)-2):6;
		cal.add(Calendar.DATE, -numberOfDays);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		return cal.getTime();
	}
	public static Date getEndOfWeek(Date now)	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(now);
		int numberOfDays = cal.get(Calendar.DAY_OF_WEEK) > 1?(cal.get(Calendar.DAY_OF_WEEK)-2):6;
		cal.add(Calendar.DATE, -numberOfDays);
		cal.add(Calendar.WEEK_OF_YEAR, +1);
		cal.set(Calendar.HOUR_OF_DAY, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		cal.set(Calendar.SECOND, -1);
		return cal.getTime();
	}
	@Deprecated
	public static Integer getNumberOfMonthsLeftThisYear(Date now)	{
		int lastMonth = getLastMonthNumber(now) + 1;
		if (lastMonth == 12)
			lastMonth = 0;
		return 12 - lastMonth;
	}
	@Deprecated
	public static Integer getThisMonthNumber(Date now)	{
		return getMonth(now);
	}
	public static Date getMidWeek(Date date)	{
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		int day = cal.get(Calendar.DAY_OF_WEEK);
		if (day==Calendar.MONDAY)
			cal.add(Calendar.DAY_OF_WEEK, +2);
		if (day==Calendar.TUESDAY)
			cal.add(Calendar.DAY_OF_WEEK, +1);
		if (day==Calendar.WEDNESDAY)
			cal.add(Calendar.DAY_OF_WEEK, 0);
		if (day==Calendar.THURSDAY)
			cal.add(Calendar.DAY_OF_WEEK, -1);
		if (day==Calendar.FRIDAY)
			cal.add(Calendar.DAY_OF_WEEK, -2);
		if (day==Calendar.SATURDAY)
			cal.add(Calendar.DAY_OF_WEEK, -3);
		if (day==Calendar.SUNDAY)
			cal.add(Calendar.DAY_OF_WEEK, -4);
		return cal.getTime();
	}
	
	public static Integer getWeeksInMonth(Date date)	{
		Integer year = getYear(date);
		Integer month = getMonth(date);
		Date dateStartOfMonth = getStartOfMonth(month, year);
		Date dateEndOfMonth = getEndOfMonth(month, year);
		int weekCount = 0;
		Date selectedDate = dateStartOfMonth;
		
		while (selectedDate.before(dateEndOfMonth))	{
			Calendar cal = Calendar.getInstance();
			cal.setTime(selectedDate);
			cal.add(Calendar.WEEK_OF_YEAR, +1);
			selectedDate = cal.getTime();
			weekCount++;
		}
		return weekCount;
	}

	public static Integer getYear(Date date)	{
		Date midWeek = getMidWeek(date);
		Calendar cal = Calendar.getInstance();
		cal.setTime(midWeek);
		return cal.get(Calendar.YEAR);
	}
	
	public static Integer getYearLastMonth(Date now)	{
		Integer yearLastMonth, lastMonth;
		Integer year = DateUtility.getYear(new Date());
		Integer thisMonth = DateUtility.getMonth(new Date());
		if (thisMonth.equals(Calendar.JANUARY))		{
			lastMonth = Calendar.DECEMBER;
			yearLastMonth = year - 1;
		} else	{
			lastMonth = thisMonth - 1;
			yearLastMonth = year;
		}
		return yearLastMonth;
	}
	public static Integer getLastMonth(Date now)	{
		Integer yearLastMonth, lastMonth;
		Integer year = DateUtility.getYear(new Date());
		Integer thisMonth = DateUtility.getMonth(new Date());
		if (thisMonth.equals(Calendar.JANUARY))		{
			lastMonth = Calendar.DECEMBER;
			yearLastMonth = year - 1;
		} else	{
			lastMonth = thisMonth - 1;
			yearLastMonth = year;
		}
		return lastMonth;
	}
	
	public static Double percentageWeekComplete(Date date)	{
		Double dayPercentage = 14.285;
		Double percentageComplete = 0.0;
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		if (cal.get(Calendar.DAY_OF_WEEK)==Calendar.MONDAY)
			percentageComplete = 0.0;
		else if (cal.get(Calendar.DAY_OF_WEEK)==Calendar.TUESDAY)
			percentageComplete = dayPercentage;
		else if (cal.get(Calendar.DAY_OF_WEEK)==Calendar.WEDNESDAY)
			percentageComplete = dayPercentage * 2;
		else if (cal.get(Calendar.DAY_OF_WEEK)==Calendar.THURSDAY)
			percentageComplete = dayPercentage * 3;
		else if (cal.get(Calendar.DAY_OF_WEEK)==Calendar.FRIDAY)
			percentageComplete = dayPercentage * 4;
		else if (cal.get(Calendar.DAY_OF_WEEK)==Calendar.SATURDAY)
			percentageComplete = dayPercentage * 5;
		else if (cal.get(Calendar.DAY_OF_WEEK)==Calendar.SUNDAY)
			percentageComplete = dayPercentage * 6;
		
		if (cal.get(Calendar.HOUR_OF_DAY) > 12)
			percentageComplete = percentageComplete + (dayPercentage/3);
		if (cal.get(Calendar.HOUR_OF_DAY) > 18)
			percentageComplete = percentageComplete + (dayPercentage*2/3);
		
		return percentageComplete/100;
	}
	public static Double percentageMonthComplete(Date date)	{
		Integer numberOfWeeks = getWeeksInMonth(date);
		Integer week = getWeekNumberOfMonth(date);
		Integer completedWeeks = week-1;
		Double weekPercentage = 1.0/numberOfWeeks;
		Double currentWeekPercentageComplete = percentageWeekComplete(date);
		Double percentageMonthComplete = (weekPercentage * completedWeeks) + (weekPercentage * currentWeekPercentageComplete);
		return percentageMonthComplete;
	}
	
	public static Date getEndOfYear(Date date) {
		int year = getYear(date);
		return getEndOfMonth(Calendar.DECEMBER, year);
	}
	public static Date getEndOfNextQuarter(Date now)	{
		Date date = DateUtility.addMonths(now, 1);
		int year = getYear(date);
		int month = getMonth(date);
		int quarter = Math.round((month + 1 + 2) / 3);
		switch (quarter)	{
		case (1):
			month = Calendar.MARCH;
			break;
		case (2):
			month = Calendar.JUNE;
			break;
		case(3):
			month = Calendar.SEPTEMBER;
			break;
		case(4):
			month = Calendar.DECEMBER;
			break;
		case (5):
			year = year + 1;
			month = Calendar.MARCH;
			break;
		}
		return getEndOfMonth(month, year);
	}
	public static Integer getWeeksTo(Date fromDate, Date toDate)	{
		if (fromDate.before(toDate))	{
			int toYear = getYear(toDate);
			int toWeek = getWeekNumberOfYear(toDate);
			int fromYear = getYear(fromDate);
			int fromWeek = getWeekNumberOfYear(fromDate);
			if (toYear>fromYear)	{
				toYear = toYear - fromYear;
				toWeek = (toYear*52) + toWeek;
				toWeek = toWeek - fromWeek + 1;
				return toWeek;
			} else {
				return toWeek - fromWeek + 1;
			}
			
		}	else
		return 0;
	}
	public static Integer getMonthsTo(Date fromDate, Date toDate)	{
		if (fromDate.before(toDate))	{
			int toYear = getYear(toDate);
			int toMonth = getMonth(toDate);
			int fromYear = getYear(fromDate);
			int fromMonth = getMonth(fromDate);
			if (toYear>fromYear)	{
				toYear = toYear - fromYear;
				toMonth = (toMonth + (toYear*12)) - fromMonth + 1;
				return  toMonth;
			} else {
				return toMonth - fromMonth + 1;
			}
			
		}	else
		return 0;
	}
	public static Date addDays(Date date, int days)		{
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.DAY_OF_WEEK, days);
		return cal.getTime();
	}
	public static Date addHours(Date date, int hours)		{
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.HOUR_OF_DAY, hours);
		return cal.getTime();
	}
	public static Date addWeeks(Date date, int weeks)		{
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.WEEK_OF_YEAR, weeks);
		return cal.getTime();
	}
	public static Date addMonths(Date date, int months)		{
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.MONTH, months);
		return cal.getTime();
	}
	
	public static Date convertStringToDate(String dateString)	{
		String pattern = "dd/MM/yyyy";
		SimpleDateFormat format = new SimpleDateFormat(pattern);
		Date date = new Date();
		try	{
			date = format.parse(dateString);
		} catch (Exception e)	{
			return null;
		}		
		return date;
	}
	public static String retrieveTodaysSimpleFormatDate()	{
		return convertDateToString(new Date());
	}
	public static String convertDateToString(Date date)	{
		String pattern = "dd/MM/yyyy";
		SimpleDateFormat format = new SimpleDateFormat(pattern);
		if (date!=null)	{
			return format.format(date);
		} else {
			return "";
		}
	}	
}
